using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using AandEDLL.DataAccess;
using AandEDLL.DataAccess.CategoryDSTableAdapters;
using AandEDLL.DataAccess.ItemDSTableAdapters;
using AandEDLL.DataAccess.UserDSTableAdapters;
using AandEDLL.DataAccess.Visit;
using System.Windows.Forms;

namespace AandEDLL
{
    public class Accessor
    {
        #region Item
        public static bool SaveItems(List<Item> itemList)
        {
            ItemTableAdapter ita = new ItemTableAdapter();

                foreach (Item item in itemList)
                {
                    InsertItem(item);
                }
            
            

            return true;
        }

        public static void InsertItem(Item item)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            item.accept(ValidationVisitor.getInstance());
            try
            {
                ita.Insert(item.User.UserID, item.Source, item.CategoryID, item.ItemName, item.SearchDate, item.Description, item.URL, item.Price);

            }
            catch (Exception e)
            {
                throw new Exception("Unable to insert " + item.ItemName + "in to the database");
            }
        }

        public static bool UpdateItemCategory(List<Item> itemList)
        {
            ItemTableAdapter ita = new ItemTableAdapter();

            try
            {
                foreach (Item item in itemList)
                {
                    ita.UpdateItemCategory(item.CategoryID, item.ItemID, item.ItemID);
                }
            }
            catch (Exception err)
            {
                throw new Exception(err.Message);
            }

            return true;
        }

        private void DeleteItems(Item[] values)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            foreach (Item item in values)
            {
                deleteItem(item);
            }
        }

        public static bool DeleteItems(List<Item> itemList)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            try
            {
                foreach (Item item in itemList)
                {
                    deleteItem(item);
                }
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine("DeleteItems: " + err.Message);
                return false;
            }

            return true;
        }

        public static bool deleteItem(Item item)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            try
            {
                ita.DeleteQuery(item.ItemID);
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine("deleteItem: " + err.Message);
                return false;
            }
            return true;
        }

        public static List<Item> GetSavedItems(User user)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            ItemDS.ItemDataTable table = ita.GetItemsByUser(user.UserID);
            List<Item> list = new List<Item>();
            Dictionary<int, String> catDictionary = GetCategoryDictionary();
            foreach (ItemDS.ItemRow row in table)
            {
                Item item = new Item();
                item.ItemID = row.ItemID;
                item.User = GetUserByID(row.UserID);
                item.ItemName = row.ItemName;                

                if (!row.IsSourceNull())
                    item.Source = row.Source;

                if (!row.IsCategoryIDNull() && row.CategoryID != 0)
                {                    
                    item.CategoryID = row.CategoryID;
                    item.Category = catDictionary[item.CategoryID];
                }

                if (!row.IsSearchDateNull())
                    item.SearchDate = row.SearchDate;

                if (!row.IsDescriptionNull())
                    item.Description = row.Description;

                if (!row.IsURLNull())
                    item.URL = row.URL;

                if (!row.IsPriceNull())
                    item.Price = row.Price;

                list.Add(item);
            }

            return list;
        }

        private void UpdateItems(List<Item> values)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            foreach (Item item in values)
            {
                ita.UpdateQuery(item.User.UserID, item.Source, item.CategoryID, item.ItemName, item.SearchDate,
                    item.Description, item.URL, item.Price, item.ItemID);
            }
        }
        #endregion

        #region User
        public static int CreateUser(User user)
        {
            UserTableAdapter uta = new UserTableAdapter();
            user.accept(ValidationVisitor.getInstance());

            // Create user
            uta.CreateUser(user.UserName, user.Password, user.Admin, new DateTime(2000,1,1));

            UserDS.UserDataTable dt = uta.GetData();
          
            UserDS.UserRow[] rows = (UserDS.UserRow[])dt.Select("[UserName] = '"
                + user.UserName + "' AND [Password] = '" + user.Password + "'");

            return rows[0].UserID;
        }
        public static bool UpdateUser(User user)
        {
            UserTableAdapter uta = new UserTableAdapter();
            //user.accept(ValidationVisitor.getInstance());
            try
            {
                uta.UpdateQuery(user.UserName, user.Password, user.Admin, user.LastLoginDate, user.UserID);
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        public static void DeleteUser(User user)
        {
            ItemTableAdapter ita = new ItemTableAdapter();
            ita.DeleteByUserQuery(user.UserID);
            UserTableAdapter uta = new UserTableAdapter();
            uta.DeleteQuery(user.UserID);
        }
        public static List<User> SelectUser()
        {
            UserDS.UserDataTable table = new UserTableAdapter().GetData();

            List<User> list = new List<User>();
            foreach (UserDS.UserRow row in table)
            {
                User item = new User();
                item.UserID = row.UserID;
                item.UserName = row.UserName;
                item.Password = row.Password;
                item.Admin = row.Admin;

                if (!row.IsLastLoginDateNull())
                    item.LastLoginDate = row.LastLoginDate;

                list.Add(item);
            }

            return list;
        }

        public static User AuthenticateUser(string userName, string password)
        {
            UserDS.UserDataTable dt = new UserTableAdapter().AuthenticateUser(userName, password);

            if (dt == null || dt.Rows.Count == 0 || dt[0].Password != password)
                throw new Exception("Invalid user name and password.");

            User user = new User();
            user.UserID = dt[0].UserID;
            user.UserName = dt[0].UserName;
            user.Password = dt[0].Password;
            user.Admin = dt[0].Admin;

            if (!dt[0].IsLastLoginDateNull())
                user.LastLoginDate = dt[0].LastLoginDate;

            return user;
        }

        public static User GetUserByID(int id)
        {
            UserDS.UserDataTable table = new UserTableAdapter().GetUserByID(id);
            if (table == null || table.Rows.Count < 1)
                throw new Exception("Invalid User name/Password");

            User user = new User();
            user.UserID = table[0].UserID;
            user.UserName = table[0].UserName;
            user.Admin = table[0].Admin;

            if (!table[0].IsLastLoginDateNull())
                user.LastLoginDate = table[0].LastLoginDate;

            return user;
        }

        public static int GetNumAdmins()
        {
            UserTableAdapter uta = new UserTableAdapter();
            return (int)uta.GetNumAdmins();
        }
        #endregion

        #region Category
        public static void insertCategory(Category[] values)
        {          
            CategoryTableAdapter cta = new CategoryTableAdapter();
            foreach (Category category in values)
            {
                insertCategory(category);
            }            
        }

        public static void insertCategory(List<Category> values)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            foreach (Category category in values)
            {
                insertCategory(category);
            }
        }

        public static void insertCategory(Category category)
        {

            CategoryTableAdapter cta = new CategoryTableAdapter();         
            //validation occurs here.
            try
            {
                category.accept(ValidationVisitor.getInstance());
                cta.InsertCategory(category.Name, category.Description, category.SavedDate);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        public static void deleteCategory(List<Category> values)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            try
            {

                foreach (Category category in values)
                {
                    deleteCategory(category);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }


        }

        public static void deleteCategory(Category[] values)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            try
            {
                foreach (Category category in values)
                {
                    deleteCategory(category);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }

        }

        public static void deleteCategory(Category category)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            ItemTableAdapter ita = new ItemTableAdapter();
            try
            {
                //delete items attached to this category
                ita.DeleteByCategoryQuery(category.CategoryID);
                cta.DeleteQuery(category.CategoryID);
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine("deleteCategory: " + err.Message);
            }
        }

        public static List<Category> getCategories()
        {
            try
            {

                CategoryTableAdapter cta = new CategoryTableAdapter();
                CategoryDS.CategoryDataTable table = cta.GetData();
                List<Category> list = new List<Category>();
            

                foreach (CategoryDS.CategoryRow row in table)
                {
                    Category category = new Category();
                    category.CategoryID = row.CategoryID;
                    category.Name = row.Name;
                    category.Description = row.Description;
                    category.SavedDate = row.SavedDate;

                    if (!row.IsSavedDateNull())
                        category.SavedDate = row.SavedDate;

                    list.Add(category);
                }
                return list;
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        public static void updateCategory(List<Category> values)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            try
            {
                foreach (Category category in values)
                {
                    updateCategory(category);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        public static void updateCategory(Category[] values)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            try
            {


                foreach (Category category in values)
                {
                    updateCategory(category);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        public static void updateCategory(Category category)
        {
            CategoryTableAdapter cta = new CategoryTableAdapter();
            //validation occurs here.
            try
            {
                category.accept(ValidationVisitor.getInstance());
                cta.UpdateQuery(category.Name, category.Description, category.SavedDate, category.CategoryID);
            }
            catch(Exception e)
            {
                throw new Exception(e.Message);
            }
        }
        private static Dictionary<int, String> GetCategoryDictionary()
        {
            CategoryDS.CategoryDataTable table = new CategoryTableAdapter().GetData();
            Dictionary<int, String> map = new Dictionary<int, String>();
            try
            {
                foreach (CategoryDS.CategoryRow row in table)
                {
                    map.Add(row.CategoryID, row.Name);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            return map;
        }
        #endregion
    }
}
